import * as React from 'react';
import PropTypes from "prop-types";
import { View } from "react-native";
import { InputItem, Toast } from '@ant-design/react-native';

class Form extends React.PureComponent {
    constructor(props, context) {
        super(props, context);
        this.validationComponents = [];
        this.attachToForm = this.attachToForm.bind(this);
    }

    getChildContext() {
        return {
            form: {
                attachToForm: this.attachToForm,
            },
        };
    }

    isValid() {
        return this.validationComponents.every(component => component.isValid(this.checkForm));
    }

    validate() {
        const { onSubmit, onError } = this.props;
        if (this.isValid()) {
            onSubmit();
            return;
        }

        if (onError) {
            onError();
        }
    }

    attachToForm(component) {
        this.validationComponents.push(component);
    }

    render() {
        const { children, ...rest } = this.props;
        return <View {...rest}>{children}</View>;
    }
}

class Input extends React.PureComponent {
    state = {
        hasError: false
    }

    constructor(props, context) {
        super(props, context);
        context.form.attachToForm(this);
    }

    checkForm = {
        validate: function (data, rule, checkRule) {
            switch (rule) {
                case 'string':
                    var reg = new RegExp('^.{' + checkRule + '}$');
                    if (!reg.test(data)) {
                        return false;
                    }
                    break;
                case 'int':
                    var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + checkRule + '}$');
                    if (!reg.test(data)) {
                        return false;
                    }
                    break;
                case 'between':
                    if (!this.isNumber(data)) {
                        return false;
                    }
                    var minMax = checkRule.split(',');
                    minMax[0] = Number(minMax[0]);
                    minMax[1] = Number(minMax[1]);
                    if (data > minMax[1] || data < minMax[0]) {
                        return false;
                    }
                    break;
                case 'betweenD':
                    var reg = /^-?[1-9][0-9]?$/;
                    if (!reg.test(data)) {
                        return false;
                    }
                    var minMax = checkRule.split(',');
                    minMax[0] = Number(minMax[0]);
                    minMax[1] = Number(minMax[1]);
                    if (data > minMax[1] || data < minMax[0]) {
                        return false;
                    }
                    break;
                case 'betweenF':
                    var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
                    if (!reg.test(data)) {
                        return false;
                    }
                    var minMax = checkRule.split(',');
                    minMax[0] = Number(minMax[0]);
                    minMax[1] = Number(minMax[1]);
                    if (data > minMax[1] || data < minMax[0]) {
                        return false;
                    }
                    break;
                case 'same':
                    if (data != checkRule) {
                        return false;
                    }
                    break;
                case 'notsame':
                    if (data == checkRule) {
                        return false;
                    }
                    break;
                case 'email':
                    var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
                    if (!reg.test(data)) {
                        return false;
                    }
                    break;
                case 'phoneno':
                    if (!this.isMobile(data)) {
                        return false;
                    }
                    break;
                case 'zipcode':
                    var reg = /^[0-9]{6}$/;
                    if (!reg.test(data)) {
                        return false;
                    }
                    break;
                case 'reg':
                    var reg = new RegExp(checkRule);
                    if (!reg.test(data)) {
                        return false;
                    }
                    break;
                case 'in':
                    if (checkRule.indexOf(data) == -1) {
                        return false;
                    }
                    break;
                case 'required':
                    if (data == null || data.length < 1) {
                        return false;
                    }
                    break;
            }
            return true;
        },
        isNumber: function (checkVal) {
            var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
            return reg.test(checkVal);
        },
        isMobile: function (checkVal) {
            var reg = /^1[0-9]{10,10}$/;
            return reg.test(checkVal);
        }
    }

    isValid = () => {
        let check = !this.checkForm.validate(this.props.value, this.props.rule, this.props.checkRule);
        if (check) {
            Toast.info(this.props.error, 1);
        }
        this.setState({
            hasError: check,
        });
        return !check;
    }

    onErrorClick = () => {
        if (this.state.hasError) {
            Toast.info(this.props.error, 1);
        }
    }

    onChange = (value) => {
        let check = !this.checkForm.validate(this.props.value, this.props.rule, this.props.checkRule);
        this.setState({
            hasError: check,
        });
        this.props.onChange(value);
    }

    render() {
        return (
            <InputItem
                type={this.props.type}
                placeholder={this.props.placeholder}
                error={this.state.hasError}
                onErrorClick={this.onErrorClick}
                onChange={this.onChange}
                value={this.props.value}
            >{this.props.children}</InputItem>
        );
    }
}

Form.childContextTypes = {
    form: PropTypes.element.object,
};

Form.propTypes = {
    onSubmit: PropTypes.func,
    onError: PropTypes.func,
};

Input.contextTypes = {
    form: PropTypes.object,
};

export { Form, Input }